<?php

/**
 * Подключает и выполняет файл
 * @param string $file полный путь к файлу+имя
 * @param array $params массив параметров
 * @param boolean $once предотвращает повторное включение файла
 * @return string Всё, что выводится файлом
 */
function includeFile($file, $params = array(), $once = false) {
    ob_start();
    if (is_file($file)) {
        if ($once) include_once $file;
        else include $file;
    }
    return ob_get_clean();
}

function reLocate($url) {
    header("Location: $url");
    die("Redirecting to: $url");
}

function inlineReLocate($url) {
    echo includeFile(APP_PAGE_PARTS . 'inline_relocate.php', array('relocate' => $url));
}

function getDatasources($reset = false) {
    static $data;

    if (!$reset && is_array($data)) return $data;

    $data = array();
    $res = DB::query('SELECT * FROM `admin_conn_history`');
    if (!$res || !DB::state()) return $data;

    while ($row = mysqli_fetch_array($res, MYSQLI_ASSOC)) {
        $id = Arr::getValue($row, 'id', FALSE);
        if ($id) $data[$id] = $row;
    }

    return $data;
}

function getClientOSs($reset = false) {
    static $data;

    if (!$reset && is_array($data))  return $data;

    $data = array();
    $res = DB::query('SELECT * FROM `admin_clientos`');
    if (!$res || !DB::state())  return $data;

    while ($row = mysqli_fetch_array($res, MYSQLI_ASSOC)) {
        $id = Arr::getValue($row, 'id', FALSE);
        if ($id) $data[$id] = $row;
    }

    return $data;
}

function getClientDbTypes($reset = false) {
    static $data;

    if (!$reset && is_array($data)) return $data;

    $data = array();
    $res = DB::query('SELECT * FROM `admin_clientdbtypes`');
    if (!$res || !DB::state()) return $data;

    while ($row = mysqli_fetch_array($res, MYSQLI_ASSOC)) {
        $id = Arr::getValue($row, 'id', FALSE);
        if ($id) $data[$id] = $row;
    }

    return $data;
}

function getClientApps($reset = false) {
    static $data;

    if (!$reset && is_array($data)) return $data;

    $data = array();
    $res = DB::query('SELECT * FROM `admin_clientapps`');
    if (!$res || !DB::state())  return $data;

    while ($row = mysqli_fetch_array($res, MYSQLI_ASSOC)) {
        $id = Arr::getValue($row, 'id', FALSE);
        if ($id) $data[$id] = $row;
    }

    return $data;
}




function getObjTypes($reset = false) {
    static $data;

    if (!$reset && is_array($data)) return $data;

    $data = array();
    $res = DB::query('SELECT ot.*, dt.name as datatypename, dt.unit FROM `admin_objtypes` ot LEFT JOIN `admin_datatypes` dt ON ot.datatype = dt.id');
    if (!$res || !DB::state()) return $data;

    while ($row = mysqli_fetch_array($res, MYSQLI_ASSOC)) {
        $id = Arr::getValue($row, 'id', FALSE);
        if ($id) $data[$id] = $row;
    }

    return $data;
}





function getDataTypes($reset = false) {
    static $data;

    if (!$reset && is_array($data))  return $data;

    $data = array();
    $res = DB::query('SELECT * FROM `admin_datatypes`');
    if (!$res || !DB::state()) return $data;

    while ($row = mysqli_fetch_array($res, MYSQLI_ASSOC)) {
        $id = Arr::getValue($row, 'id', FALSE);
        if ($id) $data[$id] = $row;
    }

    return $data;
}

function getBuildTypes($reset = false) {
    static $data;

    if (!$reset && is_array($data)) return $data;

    $data = array();
    $res = DB::query('SELECT * FROM `admin_buildtypes`');
    if (!$res || !DB::state())
        return $data;

    while ($row = mysqli_fetch_array($res, MYSQLI_ASSOC)) {
        $id = Arr::getValue($row, 'id', FALSE);
        if ($id) $data[$id] = $row;
    }

    return $data;
}

function getAllViewsGroups($reset = false) {
    static $data;

    if (!$reset && is_array($data))  return $data;

    $data = array();
    $res = DB::query('SELECT * FROM `views_group_list`');
    if (!$res || !DB::state())
        return $data;

    while ($row = mysqli_fetch_array($res, MYSQLI_ASSOC)) {
        $id = Arr::getValue($row, 'id', FALSE);
        if ($id)  $data[$id] = $row;
    }

    return $data;
}

function getAllContacts($reset = false) {
    static $data;

    if (!$reset && is_array($data))   return $data;

    $data = array('byId' => array(), 'byFio' => array());
    $res = DB::query("SELECT *, CONCAT(lastname,' ',firstname,' ',middlename) as fio FROM `admin_contact_list` ORDER BY fio");
    if (!$res || !DB::state()) return $data;

    while ($row = mysqli_fetch_array($res, MYSQLI_ASSOC)) {
        $id = Arr::getValue($row, 'id', FALSE);
        if ($id) {
            $data['byId'][$id] = $row;
            $data['byFio'][] = $row;
        }
    }

    return $data;
}

function getAllCities($reset = false) {
    static $data;

    if (!$reset && is_array($data)) return $data;

    $data = array();
    $res = DB::query('SELECT * FROM `views_city_list`');
    if (!$res || !DB::state()) return $data;

    while ($row = mysqli_fetch_array($res, MYSQLI_ASSOC)) {
        $id = Arr::getValue($row, 'id', FALSE);
        if ($id)  $data[$id] = $row;
    }

    return $data;
}

/*
function getAllObjects_dev($reset = false) {
    static $data;

    if (!$reset && is_array($data))
        return $data;

    $data = array();
    $res = DB::query('SELECT * FROM `views_object_list_dev`'); // Всё-таки выберем все, а по ходу пьесы разберёмся.
    //$res = DB::query('SELECT * FROM `views_object_list` WHERE (dev=0 OR dev=3) AND viewable>0 AND conception<>'.CNC_CLOSED_OBJECTS);
    if (!$res || !DB::state())
        return $data;

    while ($row = mysqli_fetch_array($res, MYSQLI_ASSOC)) {
        $id = Arr::getValue($row, 'id', FALSE);
        if ($id)
            $data[$id] = $row;
    }

    return $data;
}
*/

function getAllViews_($reset = false) {
    return getAllViews($reset);
}


function getAllViews($reset = false) {
    static $data;

    if (!$reset && is_array($data))  return $data;

    $data = array();
    $res = DB::query('SELECT * FROM `views_object_list`'); // Всё-таки выберем все, а по ходу пьесы разберёмся.
    //$res = DB::query('SELECT * FROM `views_object_list` WHERE (dev=0 OR dev=3) AND viewable>0 AND conception<>'.CNC_CLOSED_OBJECTS);
    if (!$res || !DB::state())   return $data;

    while ($row = mysqli_fetch_array($res, MYSQLI_ASSOC)) {
        $id = Arr::getValue($row, 'id', FALSE);
        if ($id)  $data[$id] = $row;
    }

    return $data;
}


function getAllUserGroups($reset = false) {
    static $data;

    if (!$reset && is_array($data))return $data;

    $data = array();
    $res = DB::query('SELECT * FROM `users_group_list`');
    if (!$res || !DB::state()) return $data;

    while ($row = mysqli_fetch_array($res, MYSQLI_ASSOC)) {
        $id = Arr::getValue($row, 'id', FALSE);
        if ($id) $data[$id] = $row;
    }

    return $data;
}



function getAllUsers($reset = false) {
    static $data;

    if (!$reset && is_array($data))return $data;

    $data = array();
    $res = DB::query('SELECT * FROM `users_list` WHERE deleted < 1 ORDER BY rang DESC, first_name, last_name');
    if (!$res || !DB::state()) return $data;

    while ($row = mysqli_fetch_array($res, MYSQLI_ASSOC)) {
        $id = Arr::getValue($row, 'id', FALSE);
        if ($id) $data[$id] = $row;
    }

    return $data;
}













/**
 * Выбираем видимые объекты из массива объектов
 * @param type $objectsArray Исходный массив
 * @param type $devArray Массив значений поля dev, которые нужно интерпретировать как "видимые". По умолчанию - (0, 3, 6)
 * @return array
 */
function selectViewableObjectsFromSet($objectsArray, $devArray = array(0, 3, 6)) {
    $out = array();
    if (!is_array($objectsArray))
        return $out;

    foreach ($objectsArray as $obj) {
        $dev = Arr::getValue($obj, 'dev', -1);
        if (!in_array($dev, $devArray))
            continue;
        if (!Arr::getValue($obj, 'viewable', false))
            continue;
        if (Arr::getValue($obj, 'conception', CNC_CLOSED_OBJECTS) == CNC_CLOSED_OBJECTS)
            continue;
        $out[$obj['id']] = $obj;
    }

    return $out;
}

/**
 * Сортировка отображений по алфавиту
 * @param type $views
 * @return type
 */
function sortViewsByName(&$views) {
    return usort($views, 'cbSortByName');
}

/**
 * Сортировка отображений по алфавиту
 * функция используется как аргумент для usort()
 *
 * @param array $a сравниваемый объект
 * @param array $b сравниваемый объект
 * @return int результат сравнения (-1|0|+1)
 */
function cbSortByName($a, $b) {

    if ($a['obj_name'] == $b['obj_name']) {
        if ($a['id'] == $b['id']) return 0;
        else return ($a['id'] > $b['id']) ? 1 : -1;
    }
    return ($a['obj_name'] > $b['obj_name']) ? 1 : -1;
}



function getDataLoader($obj_id, &$msg_content) {
    try {
        // родительские классы лоадера и зависимости
        include_once APP_LIB_FILES . 'usersession.php';
        include_once RP_APP_LIB_FILES.'loader.php';


        $msg = '';
        $msg_content = '';

        if (class_exists('Loader')) {
            $loader = new Loader($obj_id);
            //Trace::rec('RES getDataLoader:: '.$loaderClass);
            if ($loader->state()) return $loader;
            else $msg_content = 'Ошибка в лоадере: '.$loader->getErrString();
        }
        else $msg_content = 'Ошибка в лоадере.';
    }
    catch (Exception $exc) {
        $msg_content = 'Exception: '.$exc->getTraceAsString();
    }
    return false;
}





function getOldLoader($obj_id, &$msg_content) {

    // родительские классы лоадера и зависимости
    include_once APP_LIB_FILES . 'usersession.php';
    include_once RP_APP_LIB_FILES . 'main_loader.php';
    include_once RP_APP_LIB_FILES . 'trcfloor.php';
    include_once RP_APP_LIB_FILES . 'lib_loaders' . DIRECTORY_SEPARATOR . 'trc_loader.php';
    include_once RP_APP_LIB_FILES . 'lib_loaders' . DIRECTORY_SEPARATOR . 'cafe_loader.php';
    include_once RP_APP_LIB_FILES . 'lib_loaders' . DIRECTORY_SEPARATOR . 'hotel_loader.php';


    $msg = '';
    $msg_content = '';
    $file = RP_APP_DATA_LOAD_FILES . "loader_" . $obj_id . ".php";
    try {
        if (is_file($file)) {
            $loaderClass = "Loader_" . $obj_id;
            if (class_exists($loaderClass)) {
                $msg_content = "FATAL: Класс лоадера $loaderClass уже определён ранее";
                return false;
            }
            include_once $file;
            if (class_exists($loaderClass)) {
                $loader = new $loaderClass();
                return $loader;
            }
            else  $msg_content = 'Ошибка в лоадере.';
        }
        else $msg_content = 'Нет доступа к файлу лоадера.';
    }
    catch (Exception $exc) {
        $msg_content = 'Exception: '.$exc->getTraceAsString();
    }

    return false;
}



function getFloorsByViewId($vid, $reset = false) {
    static $data;

    if ($reset || !is_array($data))
        $data = array();
    if (is_array(Arr::getValue($data, $vid, false)))
        return $data[$vid];
    //if (!$reset && is_array($data)) return $data;

    $arr = array('byId' => array(), 'byOrder' => array());

    $res = DB::query("SELECT * FROM `views_floors_list` WHERE view_id = $vid ORDER BY view_order");
    if (!$res || !DB::state())
        return $arr;

    while ($row = mysqli_fetch_array($res, MYSQLI_ASSOC)) {
        $id = Arr::getValue($row, 'id', FALSE);
        if ($id) {
            $fl = new Floor($row);
            $fl->readDss();
            $arr['byId'][$id] = $fl;
            $arr['byOrder'][] = $fl;
            $data[$vid] = $arr;
        }
    }

    return Arr::getValue($data, $vid, $arr);
}

function getDbTables($reset = false) {
    static $data;

    if (!$reset && is_array($data))
        return $data;

    $data = array();

    $res = DB::query("SHOW TABLES");
    if (!DB::$lastReqState) return $data;
    $key = false;
    while ($row = $res->fetch_assoc()) {
        if (!$key) { // Заранее неизвестно имя столбца
            $key = array_keys($row);
            $key = $key[0];
        }
        $data[] = Arr::getValue($row, $key, '---');
    }

    return $data;
}


function getMSDbTables($reset = false) {
    static $data;

    if (!$reset && is_array($data))
        return $data;

    $data = array();

    $res = MSDB::query("SELECT name FROM ".MSDB::$DB_NAME.".sys.objects WHERE [type]='U' AND name LIKE 'obj_%' ORDER BY name");
    if (!MSDB::$lastReqState) return $data;
    $key = false;
    while ($row = MSDB::fetchAssoc($res)) {
        if (!$key) { // Заранее неизвестно имя столбца
            $key = array_keys($row);
            $key = $key[0];
        }
        $data[] = Arr::getValue($row, $key, '---');
    }

    return $data;
}





function getObjTablesList($tableArray) {
    $tables = array();
    if (is_array($tableArray)) {
        foreach ($tableArray as $table) {
            if (isValidDataTableName($table)) $tables[] = $table;
        }
    }
    return $tables;
}




function getTableFields($tableName) {
    $data = array();

    $res = DB::query("DESCRIBE $tableName");
    if (!$res || !DB::state())
        if (!$res || !DB::state()) return $data;
    $key = false;
    while ($row = $res->fetch_assoc()) {
        if (!$key) { // Заранее неизвестно имя столбца
            $key = array_keys($row);
            $key = $key[0];
        }
        $data[] = Arr::getValue($row, $key, '---');
    }

    return $data;
}









function getViewsByTable($name) {
    $out = array();

    $q = "SELECT DISTINCT vw.*
            FROM
                `views_object_list` vw,
                `views_floors_list` fl,
                `views_floors_sensors_list` flds
            WHERE
                flds.tbl = '$name'
                && flds.floor_id = fl.id
                && fl.view_id = vw.id
                && vw.conception <> '".CNC_CLOSED_OBJECTS."'
        ";

    /*
    foreach ($vws as $obj) {
        if (
                is_array($obj)
                && !in_array(Arr::getValue($obj, 'dev', -1), array(-1/* ,5,6 * /))
                && Arr::getValue($obj, 'conception') != CNC_CLOSED_OBJECTS
                //&& Arr::getValue($obj, 'viewable', false)
                && Arr::getValue($obj, 'id_obj') == $name
        ) {
            $out[Arr::getValue($obj, 'id')] = $obj;
        }
    } //foreach $objects

     */
    $res = DB::query($q);
    if (!$res || !DB::state()) return $out;
    while ($row = $res->fetch_assoc()) {
        $out[Arr::getValue($row, 'id', 0)] = $row;
    }

    return $out;
}



/**
 * текущее время в секундах с точностью до микросекунд с 1970
 * @return float
 */
function microtime_float() {
    list($usec, $sec) = explode(" ", microtime());
    return ((float) $usec + (float) $sec);
}

/**
 * Возвращает время выполнения программы с момента начала отсчёта.
 * Если отсчёт времени не начат - запускает его
 *
 * @staticvar float $start_mt время начала отсчёта
 * @return float время, прошедшее с начала отсчёта времени
 */
function timing() {
    static $start_mt;

    if (!isset($start_mt))
        $start_mt = microtime_float();
    $out = microtime_float() - $start_mt;
    return $out;
}

/**
 * Возвращает Timestamp соответствующий 23:59:59 того дня, в котором находится переданный параметр
 * @param timestamp $daytime
 * @return  timestamp
 */
function lastMomentOfDay($daytime) {
    $dt = new DateTime();
    $dt->setTimestamp($daytime);
    $dt->setTime(23, 59, 59);
    return $dt->getTimestamp();
}

function isValidDataTableName($name) {
    $namearr = explode('_', $name);
    
    $arr = array();
    $arr[] = is_array($namearr);
    $arr[] = count($namearr) == 2;
    $arr[] = ($namearr[0] == 'obj');
    $arr[] = is_numeric($namearr[1]);
    
    return (
            is_array($namearr)
            && count($namearr) == 2
            && ($namearr[0] == 'obj')
            && is_numeric($namearr[1])
            );
}

function conceptionSelectorOptions($selectedId) {
    $conceptions = ConceptionsCollection::allSorted();
    $cnt = false;
    $out = '';

    foreach ($conceptions as $parent) {
        if ($parent instanceof RPConception) {
            if ($parent->hasChild()) {
                $out .= '<optgroup label="' . $parent->name . '" id="og_cnc_' . $parent->id . '">';
                foreach ($parent->children as $c) {
                    $sel = ($selectedId == $c->id) ? ' selected="selected" ' : ' ';
                    $out .= '<option id="opt_cnc_' . $c->id . '" value="' . $c->id . '" ' . $sel . '>' . $c->name . '</option>';
                    if ($selectedId == $c->id)
                        $cnt = true;
                }
                $out .= '</optgroup>';
            }
            else {
                $sel = ($selectedId == $parent->id) ? ' selected="selected" ' : ' ';
                $out .= '<option id="opt_cnc_' . $parent->id . '" value="' . $parent->id . '" ' . $sel . '>' . $parent->name . '</option>';
                if ($selectedId == $parent->id)
                    $cnt = true;;
            }
        }
    }

    if ($selectedId == 0 || !$cnt) {
        $out .= '<option value="0" selected="selected" disabled="disabled" style="color:red;">Выберите концепцию</option>';
    }

    return $out;
}



function fetchUser($u) {
    $u['password'] = null;
    $u['salt'] = null;
    $u['register_confirmation'] = null;
    $id = $u['id'];
    
    $localAva = UserAvatar::checkAva($id);
    $isDefAva = ($localAva == APP_HTML_DEF_AVA);
    
    if (!$u['photo'] || $isDefAva) {
        $u['photo'] = APP_HTML_DEF_AVA;
        $u['photo_exists'] = false;
    }
    else {
        if ($isDefAva) {
            UserAvatar::deleteAvaFromDB ($id);
            $u['photo'] = APP_HTML_DEF_AVA;
            $u['photo_exists'] = false;
        }
        else {
            $u['photo'] = $localAva;
            $u['photo_exists'] = true;
        }
    }


    if(strstr($u['reg_date'], "0000-00-00")) $u['reg_date'] = "";
    else $u['reg_date'] = date("d.m.Y H:i",strtotime($u['reg_date']));

    return $u;
}


/**
* Генератор пар хеш+соль
 * 
* @param string $pass незашифрованный пароль пользователя
* @return array  массив: array(salt = соль, password = хеш пароля)
*/
function generatePasswordSalt($pass) {
    $chars = str_split('~`!@#$%^&*()[]{}-_\/|\'";:,.+=<>?');
    $keys = array_rand($chars, 6);

    foreach($keys as $key) $hash['salt'][] = $chars[$key];

    $hash['salt'] = implode('', $hash['salt']);
    $hash['salt'] = md5($hash['salt']);
    $hash['password'] = md5($hash['salt'].$pass.$hash['salt']);
    return $hash;
}



?>